import * as THREE from '../../build/three.module.js';
import Stats from '../../jsm/libs/stats.module.js';

import { OrbitControls } from '../../jsm/controls/OrbitControls.js';
import { OBJLoader } from '../../jsm/loaders/OBJLoader.js';
import { GUI } from '../../jsm/libs/dat.gui.module.js';

// GUI 参数
const params = {
  material: 'normal',
  camera: 'perspective',
  side: 'double'
};
// 渲染模型面
const sides = {
  'front': THREE.FrontSide,
  'back': THREE.BackSide,
  'double': THREE.DoubleSide
};
const SCALE = 2.436143;
const BIAS = -0.428408;

// 场景
const scene = new THREE.Scene();

// 相机
const height = 500; // 正交相机横截体尺寸
const aspect = innerWidth / innerHeight;
const cameraPerspective = new THREE.PerspectiveCamera(45, aspect, 500, 3000);
cameraPerspective.position.z = 1500;
scene.add(cameraPerspective);

const cameraOrtho = new THREE.OrthographicCamera(-height * aspect, height * aspect, height, -height, 1000, 2500);
cameraOrtho.position.z = 1500;
scene.add(cameraOrtho);

// 初始化为正交相机
let camera = cameraPerspective;

// 渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(devicePixelRatio);
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement)

// 控制器
const controlsPerspective = new OrbitControls( cameraPerspective, renderer.domElement );
controlsPerspective.minDistance = 1000;
controlsPerspective.maxDistance = 2400;
controlsPerspective.enablePan = false;
controlsPerspective.enableDamping = true; // 启用阻尼效果

const controlsOrtho = new OrbitControls( cameraOrtho, renderer.domElement );
controlsOrtho.minZoom = 0.5;
controlsOrtho.maxZoom = 1.5;
controlsOrtho.enablePan = false;
controlsOrtho.enableDamping = true;

// 光照
// 环境光
const al = new THREE.AmbientLight(0xffffff, 0.1);
scene.add(al);
// 点光源
const pl = new THREE.PointLight(0xff0000, 0.5);
pl.position.z = 25000;
scene.add(pl);
// 点光源2
const pl2 = new THREE.PointLight(0xff6666, 1);
camera.add(pl2);
// 点光源3
const pl3 = new THREE.PointLight(0x0000ff, 0.5);
pl3.position.x = -1000;
pl3.position.z = 1000;
scene.add(pl3);

// 加载三种贴图
const textureLoader = new THREE.TextureLoader();
const normalMap = textureLoader.load('../../models/obj/ninja/normal.jpg');
const aoMap = textureLoader.load('../../models/obj/ninja/ao.jpg');
const displacementMap = textureLoader.load('../../models/obj/ninja/displacement.jpg');

// 标准材质
const materialStandard = new THREE.MeshStandardMaterial({
  color: 0xffffff,

  metalness: 0.5,
  roughness: 0.5,

  displacementMap: displacementMap,
  displacementScale: SCALE,
  displacementBias: BIAS,

  aoMap: aoMap,

  normalMap: normalMap,
  normalScale: new THREE.Vector2(1, -1),

  side: THREE.DoubleSide
});
// 基础深度材质
const materialDepthBasic = new THREE.MeshDepthMaterial( {
  depthPacking: THREE.BasicDepthPacking,

  displacementMap: displacementMap,
  displacementScale: SCALE,
  displacementBias: BIAS,

  side: THREE.DoubleSide
} );
// RGBA深度材质
const materialDepthRGBA = new THREE.MeshDepthMaterial( {
  depthPacking: THREE.RGBADepthPacking,

  displacementMap: displacementMap,
  displacementScale: SCALE,
  displacementBias: BIAS,

  side: THREE.DoubleSide
} );
// 法线材质
const materialNormal = new THREE.MeshNormalMaterial( {
  displacementMap: displacementMap,
  displacementScale: SCALE,
  displacementBias: BIAS,

  normalMap: normalMap,
  normalScale: new THREE.Vector2( 1, - 1 ),

  side: THREE.DoubleSide
} );

// 加载几何体模型
let mesh;
const loader = new OBJLoader();
loader.load('../../models/obj/ninja/ninjaHead_Low.obj', group => {
  const geo = group.children[0].geometry;
  geo.attributes.uv2 = geo.attributes.uv;
  geo.center();

  mesh = new THREE.Mesh(geo, materialNormal);
  mesh.scale.multiplyScalar(25);
  scene.add(mesh);
})

// 统计
const stats = new Stats();
document.body.appendChild(stats.dom);

// GUI
const gui = new GUI();
gui.add(params, 'material', ['standard', 'normal', 'depthBasic', 'depthRGBA']);
gui.add(params, 'camera', ['perspective', 'ortho']);
gui.add(params, 'side', ['front', 'back', 'double']);

// 渲染动画
const render = () => {

  if (mesh) {
    // 设置材质
    let material = mesh.material;

    switch(params.material) {
      case 'standard': material = materialStandard; break;
      case 'normal': material = materialNormal; break;
      case 'depthBasic': material = materialDepthBasic; break;
      case 'depthRGBA': material = materialDepthRGBA; break;
      default: break;
    }

    if (sides[ params.side ] !== material.side) {
      switch (params.side) {
        case 'front': material.side = THREE.FrontSide; break;
        case 'back': material.side = THREE.BackSide; break;
        case 'double': material.side = THREE.DoubleSide; break;
      }

      material.needUpdate = true;
    }

    mesh.material = material;
  }

  switch (params.camera) {
    case 'perspective': camera = cameraPerspective; break;
    case 'ortho': camera = cameraOrtho; break;
    default: break;
  }

  renderer.render(scene, camera);
}

// 驱动函数
const animate = () => {
  requestAnimationFrame(animate);

  stats.update();
  render();
}
animate();

// 事件处理
// window resize 事件
const handleWindowResize = () => {
  const aspect = innerWidth / innerHeight;
  const height = innerHeight;

  camera.aspect = aspect;

  camera.left = -height * aspect;
  camera.right = height * aspect;
  camera.top = height;
  camera.bottom = -height;

  camera.updateProjectionMatrix();

  renderer.setSize(innerWidth, height);
}
window.addEventListener('resize', handleWindowResize, false);